angular.module('leaflet-directive').factory('leafletMapDefaults', function($q, leafletHelpers) {
  function _getDefaults() {
    return {
      keyboard: true,
      dragging: true,
      worldCopyJump: false,
      doubleClickZoom: true,
      scrollWheelZoom: true,
      tap: true,
      touchZoom: true,
      zoomControl: true,
      zoomsliderControl: false,
      zoomControlPosition: 'topleft',
      attributionControl: true,
      controls: {
        layers: {
          visible: true,
          position: 'topright',
          collapsed: true,
        },
      },
      nominatim: {
        server: ' http://nominatim.openstreetmap.org/search',
      },
      crs: L.CRS.EPSG3857,
      tileLayer: '//{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',
      tileLayerOptions: {
        attribution: '&copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors',
      },
      path: {
        weight: 10,
        opacity: 1,
        color: '#0000ff',
      },
      center: {
        lat: 0,
        lng: 0,
        zoom: 1,
      },
    };
  }

  var isDefined = leafletHelpers.isDefined;
  var isObject = leafletHelpers.isObject;
  var obtainEffectiveMapId = leafletHelpers.obtainEffectiveMapId;
  var defaults = {};

  // Get the _defaults dictionary, and override the properties defined by the user
  return {
    reset: function() {
      defaults = {};
    },

    getDefaults: function(scopeId) {
      var mapId = obtainEffectiveMapId(defaults, scopeId);
      return defaults[mapId];
    },

    getMapCreationDefaults: function(scopeId) {
      var mapId = obtainEffectiveMapId(defaults, scopeId);
      var d = defaults[mapId];

      var mapDefaults = {
        maxZoom: d.maxZoom,
        keyboard: d.keyboard,
        dragging: d.dragging,
        zoomControl: d.zoomControl,
        doubleClickZoom: d.doubleClickZoom,
        scrollWheelZoom: d.scrollWheelZoom,
        tap: d.tap,
        touchZoom: d.touchZoom,
        attributionControl: d.attributionControl,
        worldCopyJump: d.worldCopyJump,
        crs: d.crs,
      };

      if (isDefined(d.minZoom)) {
        mapDefaults.minZoom = d.minZoom;
      }

      if (isDefined(d.zoomAnimation)) {
        mapDefaults.zoomAnimation = d.zoomAnimation;
      }

      if (isDefined(d.fadeAnimation)) {
        mapDefaults.fadeAnimation = d.fadeAnimation;
      }

      if (isDefined(d.markerZoomAnimation)) {
        mapDefaults.markerZoomAnimation = d.markerZoomAnimation;
      }

      if (d.map) {
        for (var option in d.map) {
          mapDefaults[option] = d.map[option];
        }
      }

      return mapDefaults;
    },

    setDefaults: function(userDefaults, scopeId) {
      var newDefaults = _getDefaults();

      if (isDefined(userDefaults)) {
        newDefaults.doubleClickZoom = isDefined(userDefaults.doubleClickZoom) ? userDefaults.doubleClickZoom : newDefaults.doubleClickZoom;
        newDefaults.scrollWheelZoom = isDefined(userDefaults.scrollWheelZoom) ? userDefaults.scrollWheelZoom : newDefaults.doubleClickZoom;
        newDefaults.tap = isDefined(userDefaults.tap) ? userDefaults.tap : newDefaults.tap;
        newDefaults.touchZoom = isDefined(userDefaults.touchZoom) ? userDefaults.touchZoom : newDefaults.doubleClickZoom;
        newDefaults.zoomControl = isDefined(userDefaults.zoomControl) ? userDefaults.zoomControl : newDefaults.zoomControl;
        newDefaults.zoomsliderControl = isDefined(userDefaults.zoomsliderControl) ? userDefaults.zoomsliderControl : newDefaults.zoomsliderControl;
        newDefaults.attributionControl = isDefined(userDefaults.attributionControl) ? userDefaults.attributionControl : newDefaults.attributionControl;
        newDefaults.tileLayer = isDefined(userDefaults.tileLayer) ? userDefaults.tileLayer : newDefaults.tileLayer;
        newDefaults.zoomControlPosition = isDefined(userDefaults.zoomControlPosition) ? userDefaults.zoomControlPosition : newDefaults.zoomControlPosition;
        newDefaults.keyboard = isDefined(userDefaults.keyboard) ? userDefaults.keyboard : newDefaults.keyboard;
        newDefaults.dragging = isDefined(userDefaults.dragging) ? userDefaults.dragging : newDefaults.dragging;

        if (isDefined(userDefaults.controls)) {
          angular.extend(newDefaults.controls, userDefaults.controls);
        }

        if (isObject(userDefaults.crs)) {
          newDefaults.crs = userDefaults.crs;
        } else if (isDefined(L.CRS[userDefaults.crs])) {
          newDefaults.crs = L.CRS[userDefaults.crs];
        }

        if (isDefined(userDefaults.center)) {
          angular.copy(userDefaults.center, newDefaults.center);
        }

        if (isDefined(userDefaults.tileLayerOptions)) {
          angular.copy(userDefaults.tileLayerOptions, newDefaults.tileLayerOptions);
        }

        if (isDefined(userDefaults.maxZoom)) {
          newDefaults.maxZoom = userDefaults.maxZoom;
        }

        if (isDefined(userDefaults.minZoom)) {
          newDefaults.minZoom = userDefaults.minZoom;
        }

        if (isDefined(userDefaults.zoomAnimation)) {
          newDefaults.zoomAnimation = userDefaults.zoomAnimation;
        }

        if (isDefined(userDefaults.fadeAnimation)) {
          newDefaults.fadeAnimation = userDefaults.fadeAnimation;
        }

        if (isDefined(userDefaults.markerZoomAnimation)) {
          newDefaults.markerZoomAnimation = userDefaults.markerZoomAnimation;
        }

        if (isDefined(userDefaults.worldCopyJump)) {
          newDefaults.worldCopyJump = userDefaults.worldCopyJump;
        }

        if (isDefined(userDefaults.map)) {
          newDefaults.map = userDefaults.map;
        }

        if (isDefined(userDefaults.path)) {
          newDefaults.path = userDefaults.path;
        }
      }

      var mapId = obtainEffectiveMapId(defaults, scopeId);
      defaults[mapId] = newDefaults;
      return newDefaults;
    },
  };
});
